// --------------------------------------------------------------------------------------------------------------------
// <copyright file="IOrderTracker.cs" company="Open Trader">
//   Copyright (c) David Denis (david.denis@systemathics.com)
// </copyright>
// <summary>
//   |  Open Trader - The Open Source Systematic Trading Platform
//   |
//   |  This program is free software: you can redistribute it and/or modify
//   |  it under the terms of the GNU General Public License as published by
//   |  the Free Software Foundation, either version 2 of the License, or
//   |  (at your option) any later version.
//   |
//   |  This program is distributed in the hope that it will be useful,
//   |  but WITHOUT ANY WARRANTY; without even the implied warranty of
//   |  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//   |  GNU General Public License for more details.
//   |
//   |  You should have received a copy of the GNU General Public License
//   |  along with this program.  If not, see http://www.gnu.org/licenses
//   |
//   |  Up to date informations about Open Trader can be found at :
//   |    http://opentrader.org
//   |    http://opentrader.codeplex.com
//   |
//   |  For professional services, please visit us at :
//   |    http://www.systemathics.com
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace Org.OpenTrader.Framework.Forge.Interfaces
{
    #region Using Directives

    using System;

    using Org.OpenTrader.Framework.Forge.Enums;
    using Org.OpenTrader.Framework.Forge.Events;

    #endregion

    /// <summary>
    /// Used to track and build-up information of the "live" aspect of orders (a superset of EOrderStatus, executions and reports)
    /// </summary>
    public interface IOrderTrackingCell
    {
        #region Properties

        /// <summary>
        /// The order was Acknowledged (Market Reply)
        /// </summary>
        bool Acknowledged { get; }

        /// <summary>
        /// Order "Ack" DateTime
        /// </summary>
        DateTime AckStamp { get; }

        /// <summary>
        /// This order is still alive ?
        /// </summary>
        bool Alive { get; }

        /// <summary>
        /// This order is a buy order ?
        /// </summary>
        bool Buy { get; }

        /// <summary>
        /// Order "Cancel" DateTime : When the order has received the ack of the Cancel
        /// </summary>
        DateTime CancelAckStamp { get; }

        /// <summary>
        /// Is order cancelled (that is a "cancel" has been issued and and "AckCancel" has been received, or the market sent us some OutReport)
        /// </summary>
        bool Cancelled { get; }

        /// <summary>
        /// Are we currently cancelling this order ?
        /// </summary>
        bool Cancelling { get; }

        /// <summary>
        /// Cancelled quantity
        /// </summary>
        int CancelQuantity { get; }

        /// <summary>
        /// Number of rejection to Cancel this order
        /// </summary>
        int CancelRejected { get; }

        /// <summary>
        /// Order "Cancel" DateTime
        /// </summary>
        DateTime CancelStamp { get; }

        /// <summary>
        /// This order is closed ?
        /// </summary>
        bool Closed { get; }

        /// <summary>
        /// Execution correction report
        /// </summary>
        bool CorrectionReport { get; }

        /// <summary>
        /// Correction report stamp
        /// </summary>
        DateTime CorrectionReportStamp { get; }

        /// <summary>
        /// The order was ceated
        /// </summary>
        bool Created { get; }

        /// <summary>
        /// Order "Create" DateTime
        /// </summary>
        DateTime CreateStamp { get; }

        /// <summary>
        /// Delta Pending Price = Max(PendingPrice,RequestedPrice)
        /// </summary>
        double DeltaPendingPrice { get; }

        /// <summary>
        /// Delta Pending quantity = PendingQuantity - RemainingQuantity (signed qty)
        /// </summary>
        int DeltaPendingQuantity { get; }

        /// <summary>
        /// The average price of all executions (if any)
        /// </summary>
        double ExecAveragePrice { get; }

        /// <summary>
        /// The Last Exec price of this order
        /// </summary>
        double ExecPrice { get; }

        /// <summary>
        /// The quantity currently executed
        /// </summary>
        int ExecQuantity { get; }

        /// <summary>
        /// The order is fully executed, RemainingQuantity==0
        /// </summary>
        bool Executed { get; }

        /// <summary>
        /// Executions related to this order
        /// </summary>
        IExecution[] Executions { get; }

        /// <summary>
        /// Last received execution DateTime
        /// </summary>
        DateTime LastExecutionStamp { get; }

        /// <summary>
        /// Is order Modified ?
        /// </summary>
        bool Modified { get; }

        /// <summary>
        /// When the order has received the ack of the Modify
        /// </summary>
        DateTime ModifyAckStamp { get; }

        /// <summary>
        /// Are we currently Modifying this order ?
        /// </summary>
        bool Modifying { get; }

        /// <summary>
        /// Number of rejection to modify this order
        /// </summary>
        int ModifyRejected { get; }

        /// <summary>
        /// When the order has been Modified
        /// </summary>
        DateTime ModifyStamp { get; }

        /// <summary>
        /// This order is pending (new order or modify order)?
        /// </summary>
        bool NewPending { get; }

        /// <summary>
        /// Gets NextOrder.
        /// </summary>
        IOrder NextOrder { get; }

        /// <summary>
        /// The Next Order Status.
        /// </summary>
        ENextOrderStatus NextStatus { get; }

        /// <summary>
        /// This order is still open ?
        /// </summary>
        bool Open { get; }

        /// <summary>
        /// The order that is tracked here
        /// </summary>
        IOrder Order { get; }

        /// <summary>
        /// The signed executed quantity
        /// </summary>
        int OrderExecQuantity { get; }

        /// <summary>
        /// Signed Remainig quantity of the order (Order ack) :+ when buy, - when sell
        /// </summary>
        int OrderRemainingQuantity { get; }

        // OutReport

        /// <summary>
        /// Out report (order is now dead)
        /// </summary>
        bool OutReport { get; }

        /// <summary>
        /// Out report stamp
        /// </summary>
        DateTime OutReportStamp { get; }

        /// <summary>
        /// The order is partiallaly executed, RemainingQuantity!=0
        /// </summary>
        bool PartExecuted { get; }

        // CorrectionReport

        /// <summary>
        /// This order is pending ?
        /// </summary>
        bool Pending { get; }

        /// <summary>
        /// Pending price, that is, price send through the pipeline, but not acknowledged by market yet
        /// </summary>
        double PendingPrice { get; }

        /// <summary>
        /// Pending quantity, that is, quantity send through the pipeline, but not acknowledged by market yet
        /// </summary>
        int PendingQuantity { get; }

        /// <summary>
        /// Order was rejected
        /// </summary>
        bool Rejected { get; }

        /// <summary>
        /// Reject reason
        /// </summary>
        string RejectReason { get; set; }

        /// <summary>
        /// Order "Reject" DateTime
        /// </summary>
        DateTime RejectStamp { get; }

        /// <summary>
        /// Remainig quantity of the order (Order ack)
        /// </summary>
        int RemainingQuantity { get; }

        /// <summary>
        /// Requested Price of the order
        /// </summary>
        double RequestedPrice { get; }

        /// <summary>
        /// Requested quantity of the order
        /// </summary>
        int RequestedQuantity { get; }

        /// <summary>
        /// This order is a sell order ?
        /// </summary>
        bool Sell { get; }

        /// <summary>
        /// Order "Send" DateTime
        /// </summary>
        DateTime SendStamp { get; }

        /// <summary>
        /// The order was sent bu the plugin
        /// </summary>
        bool Sent { get; }

        /// <summary>
        /// Order Side
        /// </summary>
        EOrderWay Side { get; }

        /// <summary>
        /// Get the status
        /// </summary>
        string StringStatus { get; }

        /// <summary>
        /// The Owner of this YCell
        /// </summary>
        IOrderTracker Tracker { get; }

        #endregion
    }

    /// <summary>
    /// The i order tracker.
    /// </summary>
    public interface IOrderTracker
    {
        #region Properties

        /// <summary>
        /// To subscribe to "tracking" events (that is, a change occured in a tracking structure)
        /// </summary>
        RemotableEventHandler<OrderTrackingEventArgs> EventCB { get; set; }

        /// <summary>
        /// Gets Instrument.
        /// </summary>
        IInstrument Instrument { get; }

        #endregion

        #region Indexers

        /// <summary>
        /// Get the cell which tracks some order
        /// </summary>
        /// <param name="orderId"></param>
        /// <returns></returns>
        IOrderTrackingCell this[Guid orderId]
        {
            get;
        }

        #endregion

        #region Public Methods

        /// <summary>
        /// Cancel this order
        /// </summary>
        /// <param name="order">
        /// </param>
        /// <returns>
        /// The cancel order.
        /// </returns>
        Status CancelOrder(IOrder order);

        /// <summary>
        /// Create an order
        /// </summary>
        /// <param name="type">
        /// </param>
        /// <param name="way">
        /// </param>
        /// <param name="price">
        /// </param>
        /// <param name="quantity">
        /// </param>
        /// <param name="bookingPath">
        /// </param>
        /// <returns>
        /// </returns>
        Status<IOrder> CreateOrder(EOrderType type, EOrderWay way, double price, int quantity, string bookingPath);

        /// <summary>
        /// Get some tracking Cells according predicate
        /// </summary>
        /// <param name="predicate">
        /// Predicate used to select Cells
        /// </param>
        /// <returns>
        /// </returns>
        IOrderTrackingCell[] GetTrackingCells(System.Linq.Expressions.Expression<Func<IOrderTrackingCell, bool>> predicate);

        /// <summary>
        /// Modify this order
        /// </summary>
        /// <param name="oldOrder">
        /// The oldOrder.
        /// </param>
        /// <param name="newOrder">
        /// The newOrder.
        /// </param>
        /// <returns>
        /// The modify order.
        /// </returns>
        Status ModifyOrder(IOrder oldOrder, IOrder newOrder);

        /// <summary>
        /// Send this order
        /// </summary>
        /// <param name="order">
        /// </param>
        /// <returns>
        /// The send order.
        /// </returns>
        Status SendOrder(IOrder order);

        #endregion
    }
}